#include "UnitDocument.h"
#include "../utils/Constantes.h"
#define DOC_NAME "documento"

using namespace convertTypes;

int cmp_t (const void* arg1, const void* arg2) {
	Termino* t1 = (Termino*)arg1;
	Termino* t2 = (Termino*)arg2;

	return (t1->word).compare(t2->word);
}

UnitDocument::UnitDocument() {
	document = -1;
	outputFile = NULL;
	v_terminos = new vector<Termino>();
}

UnitDocument::~UnitDocument() {
	delete v_terminos;
//	std::string name = DOC_NAME + intToString(document) + ".idxu";
//	remove (name.c_str());
}

void UnitDocument::removeDuplicated() {
	unsigned int i;
	vector <Termino>* v_aux = new vector<Termino>();
//	for(unsigned int i=0; i<v_terminos->size(); i++) {
//		cout << "\t\t" << i << ": " << v_terminos->at(i).word << " " << v_terminos->at(i).pos.at(0) << endl;
//	}
	unsigned int posAnterior = 0;
	string lastToken = string("");
	unsigned int posAInsertar;
	unsigned int posActual;
	for (i=0; i<v_terminos->size(); i++) {
		if (v_terminos->at(i).word.compare(lastToken) == 0) {
			posAInsertar = v_aux->size()-1;
			v_aux->at(posAInsertar).frecuency ++;

			posActual = v_terminos->at(i).pos.at(0);
			v_aux->at(posAInsertar).pos.push_back(posActual - posAnterior);
			posAnterior = posActual;

		} else {
			v_aux->push_back(v_terminos->at(i));
			posAnterior = v_terminos->at(i).pos.at(0);
		}
		lastToken = v_terminos->at(i).word;
	}

	v_terminos->clear();
	for (i=0; i<v_aux->size(); i++) v_terminos->push_back(v_aux->at(i));
	v_aux->clear();
//	if(v_aux != NULL)
	delete v_aux;

	saveOnDisk();
}

unsigned int UnitDocument::calculateDiff(vector<unsigned int> posiciones, unsigned int posicionActual) {
	unsigned int posicionAnterior = 0;
	for(unsigned int i=0; i<posiciones.size(); i++) {
		posicionAnterior += posiciones.at(i);
	}

	return (posicionActual - posicionAnterior);
}


int UnitDocument::binarySearch(string token, vector<Termino>* terminos) {
	int piso = 0;
	bool encontrado = false;
	int techo = terminos->size() - 1;
	int medio = (techo + piso) / 2;
	int pos = -1;
	int strcmp;

	while(piso <= techo && !encontrado) {
		strcmp = token.compare(terminos->at(medio).word);
		if(strcmp < 0) {
			techo = medio - 1;
		} else if (strcmp > 0) {
			piso = medio + 1;
		} else {
			encontrado = true;
			pos = medio;
		}

		medio = (techo + piso) / 2;
	}

	return pos;
}

int UnitDocument::binarySearch(string token) {
	return binarySearch(token, v_terminos);
}

void UnitDocument::printVTerminos() {
	cout << "v_terminos" << endl;
	for(unsigned int i=0; i< v_terminos->size(); i++) {
		cout << "\t" << i << ": " << v_terminos->at(i).word << endl;
	}
	cout << endl;
}

void UnitDocument::addTermino(string word, unsigned int pos) {
	Termino termino;
	termino.word = word;
	termino.pos.push_back(pos);  //se puede mejorar N1
	termino.document = document;
	termino.frecuency = 1;

	v_terminos->push_back(termino);
}

void UnitDocument::sort() {
//	clock_t chrono = clock();
//	clock_t clocks_per_sec = 1000000l;

	qsort ((void*)&(v_terminos->at(0)), v_terminos->size(), sizeof(Termino), cmp_t);

//	clock_t chrono1 = clock();
//	if(SHOW_TIME > 0)
//		cout << "\tSort time: " << ((float)chrono1-(float)chrono)/ clocks_per_sec << " s." <<endl;
//	chrono = chrono1;

	removeDuplicated();

//	chrono1 = clock();
//	if(SHOW_TIME > 0)
//		cout << "\tRemoved duplicated time: " << ((float)chrono1-(float)chrono)/ clocks_per_sec << " s." <<endl;

}

void UnitDocument::setDocN (int number) {
	document = number;
}

void UnitDocument::setTitle(string title) {
	this->title = title;
}

int UnitDocument::getDocN() {
	return document;
}

vector <Termino>* UnitDocument::getTerminos() {
	return v_terminos;
}

Termino* UnitDocument::getTermino(unsigned int index) {
	return &v_terminos->at(index);
}

void UnitDocument::saveOnDisk() {

	std::string name =  string(CARPETA_ARCHS_A_MERGEAR) + DOC_NAME + intToString(document) + ".idxu";
	outputFile = new ofstream (name.c_str(), ios::out | ios::binary);

	unsigned int i, j;
	for (i=0; i<v_terminos->size(); i++) {
		unsigned char a = v_terminos->at(i).word.size();
		outputFile->write(reinterpret_cast <char*> (&v_terminos->at(i).document), sizeof(int));
		outputFile->write(reinterpret_cast <char*> (&a), sizeof(char));
		outputFile->write(v_terminos->at(i).word.c_str(), a);
		outputFile->write(reinterpret_cast <char*> (&v_terminos->at(i).frecuency), sizeof(int));
		for (j=0; j<v_terminos->at(i).pos.size(); j++) outputFile->write(reinterpret_cast <char*> (&v_terminos->at(i).pos.at(j)), sizeof(int));
	}
	outputFile->close();
}

void UnitDocument::stdOutDoc() {
	unsigned int i, j;
	printf ("\nIndice Unitario:\n\n#doc Termino  frec pos\n");
	for (i=0; i<v_terminos->size(); i++) {
		printf ("\nD:%d - %s - F:%d - P:", v_terminos->at(i).document, v_terminos->at(i).word.c_str(), v_terminos->at(i).frecuency);
		for (j=0; j<v_terminos->at(i).pos.size(); j++) printf("%d ", v_terminos->at(i).pos.at(j));
	}
	printf("\n---------SUCCES SHOWN? ---------\n\n");
}
